home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / textool / pkstuff.c < prev    next >
C/C++ Source or Header  |  1990-10-01  |  14KB  |  619 lines

  1. /*
  2.  * This is the font part of textool, dealing with PK format files.
  3.  * The low level routines to deal with the PK format
  4.  * were transliterated from pktopx
  5.  * See the pktopx documentation for details.
  6.  * For V2.3, 29 Mar 88
  7. -  * Fixed stupid errors in skip_specials() that caused specials to be
  8. missed
  9.  
  10.  */
  11.  
  12. #include "defs.h"
  13. #include <stdio.h>
  14. #include <sys/file.h>                /* for access() stuff */
  15. #include <pixrect/pixrect_hs.h>        /* for LoadAChar() */
  16.  
  17. char    *index();
  18. int    strlen();
  19. char    *strcpy();
  20. char    *sprintf();
  21.  
  22. /* procedures in sunstuff */
  23. extern void    Fatal();
  24. extern void    Warning();
  25.  
  26. /* procedures in dvistuff */
  27. extern float    ActualFactor();
  28. extern FILE    *OpenFontFile();
  29.  
  30. /* procedures here */
  31. void    ReadCharDefs();
  32. void    LoadAChar();
  33.  
  34. /* a few global variables and data structures */
  35. #include "globals.h"
  36.  
  37. #define PK_XXX1 240
  38. #define PK_XXX2 241
  39. #define PK_XXX3 242
  40. #define PK_XXX4 243
  41. #define PK_YYY 244
  42. #define PK_POST 245
  43. #define PK_NOP 246
  44. #define PK_PRE 247
  45. #define PK_ID 89
  46.  
  47. #define ROWSIZE 64        /* maximum width of raster in 16 bit words */
  48.  
  49. static FILE *pkfp;
  50. static long pk_loc;            /* points to next byte to be read in file */
  51. static long pk_char_start;
  52. static int repeat_count;
  53. static int dyn_f;
  54. static int word_width;
  55. static int char_height;
  56. static int char_width;
  57. static Boolean got_pk_post;
  58. static Boolean turn_on;
  59. static int bit_weight;
  60. static int flag_byte;
  61. static int packet_length;
  62. static int char_code;
  63. static int tfm_width;
  64. static int hor_esc;
  65. static int vert_esc;
  66. static int h_off;
  67. static int v_off;
  68. static int nybindex;
  69. static short row[ROWSIZE];
  70. static short *rowptr;
  71. static short *imageptr;
  72.  
  73. static int power[16] =
  74.     {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80,
  75.     0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000};
  76. static int gpower[17] =
  77.     {0, 1, 3, 7, 15, 0x1f, 0x3f, 0x7f,
  78.     0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff};
  79.  
  80. #define get_pk_byte() (pk_loc++, getc(pkfp))
  81.  
  82.  
  83. int
  84. get_pk_word()
  85. {
  86.     int myword;
  87.  
  88.     myword = get_pk_byte() << 8;
  89.     return (myword + get_pk_byte());
  90. }
  91.  
  92.  
  93. int
  94. get_pk_double()
  95. {
  96.     register int mydouble;
  97.  
  98.     mydouble = get_pk_byte() << 8;
  99.     mydouble += get_pk_byte();
  100.     mydouble = (mydouble << 8) + get_pk_byte();
  101.     return ((mydouble << 8) + get_pk_byte());
  102. }
  103.  
  104.  
  105.             /*
  106.              * This returns the next nybble from the pk file
  107.              * The variable nybindex controls which nybble is
  108.              * returned. This is initialised to 0 in normal_raster()
  109.              * as a previous normal_raster() may have read an odd
  110.              * number of nybbles.
  111.              */
  112. int
  113. get_pk_nybble()
  114. {
  115.     static int mynybble;
  116.  
  117.     if (nybindex) {
  118.         nybindex = 0;
  119.         return (mynybble & 0xf);
  120.     }
  121.     else {
  122.         mynybble = get_pk_byte();
  123.         nybindex = 1;
  124.         return (mynybble >> 4);
  125.     }
  126. }
  127.  
  128.  
  129.             /*
  130.              * This returns a non-zero value if the next pk file
  131.              * bit is a one. It is only used in an if (..) so
  132.              * the actual value is not important.
  133.              * The variable bit_weight is used to count the bits
  134.              * between calls to get_pk_byte(). It is initialised
  135.              * to 0 in bitmap_raster() so a byte is fetched the
  136.              * first time.
  137.              * The function is given for illustration. The macro
  138.              * following is used for speed.
  139.              */
  140. /*
  141.  *int
  142.  *get_pk_bit()
  143.  *{
  144.  *    static int byte_for_bits;
  145.  *
  146.  *    if (bit_weight <= 1) {
  147.  *        bit_weight = 256;
  148.  *        byte_for_bits = get_pk_byte();
  149.  *    }
  150.  *    bit_weight = bit_weight >> 1;
  151.  *    return (byte_for_bits & bit_weight);
  152.  *}
  153.  */
  154. static int byte_for_bits;
  155. #define get_pk_bit() (((bit_weight<=1) ?\
  156.     (bit_weight = 128, byte_for_bits=get_pk_byte()) : (bit_weight>>=1)),\
  157.     byte_for_bits&bit_weight)
  158.  
  159.  
  160. void
  161. send_row()
  162. {
  163.     register short *dp;
  164.     register int i;
  165.     register int repcount;
  166.  
  167.     dp = imageptr;
  168.     repcount = repeat_count + 1;
  169.     while (repcount--) {
  170.         rowptr = row;
  171.         i = word_width;
  172.         while(i--)
  173.             *dp++ = *rowptr++;
  174.     }
  175.     imageptr=dp;        /* save for next call */
  176. }
  177.  
  178.  
  179. void
  180. skip_specials()
  181. {
  182.     register int i;
  183.  
  184.     do {
  185.         i = 0;
  186.         flag_byte = get_pk_byte();
  187.         if (flag_byte >= PK_XXX1)
  188.             switch (flag_byte) {
  189.                 case PK_XXX4:
  190.                     i = get_pk_byte();
  191.                 case PK_XXX3:
  192.                     i = (i<<8) + get_pk_byte();
  193.                 case PK_XXX2:
  194.                     i = (i<<8) + get_pk_byte();
  195.                 case PK_XXX1:
  196.                     i = (i<<8) + get_pk_byte();
  197.                     while (i--)
  198.                         (void)get_pk_byte();
  199.                     break;
  200.                 case PK_YYY:
  201.                     (void)get_pk_double();
  202.                     break;
  203.                 case PK_POST:
  204. #ifdef DEBUG
  205.                     if (ExtraDebug)
  206.                         fprintf(stderr, "Got pk_post in skip_specials()\n");
  207. #endif
  208.                     got_pk_post = TRUE;
  209.                     return;
  210.                 case PK_NOP:
  211.                     break;
  212.                 default:
  213.                     Fatal("Bad pk command byte (%d) in skip_specials()",
  214.                         flag_byte);
  215.                     return;
  216.             }
  217.     } while (flag_byte >= PK_XXX1);
  218. }
  219.  
  220.  
  221.             /*
  222.              * This routine returns the next run count from the pk
  223.              * character description. It will set the global repeat_count
  224.              * to any repeat count value encountered.
  225.              */
  226. int
  227. pk_packed_num()
  228. {
  229.     register int i, j;
  230.  
  231.     i = get_pk_nybble();
  232.     if (i == 0) {
  233.         do {
  234.             j = get_pk_nybble();
  235.             i++;
  236.         } while (j == 0);
  237.         while (i--)
  238.             j = (j<<4) + get_pk_nybble();
  239.         return (j - 15 + ((13 - dyn_f)<<4) + dyn_f);
  240.     }
  241.     else if (i <= dyn_f)
  242.         return (i);
  243.     else if (i < 14)
  244.         return (((i - dyn_f - 1)<<4) + get_pk_nybble() + dyn_f + 1);
  245.     else {
  246.         if (i == 14)
  247.             repeat_count = pk_packed_num();
  248.         else        /* i must be 15 */
  249.             repeat_count = 1;
  250.         return (pk_packed_num());
  251.     }
  252. }
  253.  
  254.             /*
  255.              * This deals with run count encoded rasters.
  256.              * It uses pk_packed_num() which in turn uses get_pk_nybble().
  257.              */
  258. void
  259. normal_raster(dp)
  260. short *dp;
  261. {
  262.     register int word = 0;
  263.     register int count;
  264.     register int h_bit = char_width;
  265.     register int word_weight = 16;
  266.     register int rows_left = char_height;
  267.  
  268.     repeat_count = 0;
  269.     nybindex = 0;
  270.     imageptr = dp;
  271.     rowptr = row;
  272.  
  273.     while (rows_left > 0) {
  274.         count = pk_packed_num();
  275.         while (count > 0) {
  276.             if ((count < word_weight) && (count < h_bit)) {
  277.                 if (turn_on)
  278.                     word += gpower[word_weight] - gpower[word_weight - count];
  279.                 h_bit -= count;
  280.                 word_weight -= count;
  281.                 count = 0;
  282.             }
  283.             else if ((count >= h_bit) && (h_bit <= word_weight)) {
  284.                 if (turn_on)
  285.                     word += gpower[word_weight] - gpower[word_weight - h_bit];
  286.                 *rowptr++ = word;
  287.                 send_row();
  288.                 rowptr = row;
  289.                 rows_left -= repeat_count + 1;
  290.                 repeat_count = 0;
  291.                 word = 0;
  292.                 word_weight = 16;
  293.                 count -= h_bit;
  294.                 h_bit = char_width;
  295.             }
  296.             else {
  297.                 if (turn_on)
  298.                     word += gpower[word_weight];
  299.                 *rowptr++ = word;
  300.                 word = 0;
  301.                 count -= word_weight;
  302.                 h_bit -= word_weight;
  303.                 word_weight = 16;
  304.             }
  305.         }
  306.         turn_on ^= 1;
  307.     }
  308.     if ((rows_left != 0) || (h_bit != char_width)) {
  309.         Fatal("Bad pk file - more bits than required\n");
  310.         return;
  311.     }
  312. }
  313.  
  314.  
  315.             /*
  316.              * This deals with bit mapped raster (dyn_f = 14).
  317.              * It uses get_pk_bit().
  318.              */
  319. void
  320. bitmap_raster(dp)
  321. short *dp;
  322. {
  323.     register int i;
  324.     register int j;
  325.     register int word;
  326.     register int word_weight;
  327.  
  328.     bit_weight = 0;
  329.  
  330.     for (i = 0; i < char_height; i++) {
  331.         word = 0;
  332.         word_weight = 15;
  333.         for (j = 0; j < char_width; j++) {
  334.             if (get_pk_bit())
  335.                 word += power[word_weight];
  336.             if (word_weight-- == 0) {
  337.                 *dp++ = word;
  338.                 word = 0;
  339.                 word_weight = 15;
  340.             }
  341.         }
  342.         if (word_weight < 15)
  343.             *dp++ = word;
  344.     }
  345. }
  346.  
  347.  
  348.             /*
  349.              * This reads the pk file preamble and rejects the file
  350.              * if it does not start correctly.
  351.              */
  352. void
  353. get_pk_preamble()
  354. {
  355.     register int comment_length;
  356.  
  357.     got_pk_post = FALSE;
  358.     fseek(pkfp, 0L, 0);
  359.     pk_loc = 0;
  360.     if (get_pk_byte() != PK_PRE) {
  361.         Fatal("Bad pk file - doesn't start with pk_pre\n");
  362.         return;
  363.     }
  364.     if (get_pk_byte() != PK_ID) {
  365.         Fatal("Bad pk file - wrong pk_id byte\n");
  366.         return;
  367.     }
  368.     comment_length = get_pk_byte();
  369.     while (comment_length--)
  370.         get_pk_byte();
  371.     (void)get_pk_double();
  372.     (void)get_pk_double();
  373.     (void)get_pk_double();
  374.     (void)get_pk_double();
  375. }
  376.  
  377.  
  378.             /*
  379.              * This reads the preamble for one character up to the tfm width.
  380.              * The tfm width is read as when it is stored in the char_entry
  381.              * struct it needs to be multiplied by the font "s" parameter.
  382.              * ReadCharDefs() is passed a pointer to the font_entry struct
  383.              * so it can do this whereas LoadAChar() can't.
  384.              * The rest of the char will either be skipped or read with
  385.              * get_pk_char_dimen().
  386.              * flag_byte will have been set by a previous skip_specials().
  387.              */
  388. void
  389. get_pk_char_code()
  390. {
  391.     dyn_f = flag_byte >> 4;
  392.     turn_on = (flag_byte & 0x8) >> 3;
  393.     flag_byte &= 0x7;
  394.     pk_char_start = pk_loc - 1; /* - 1 as flag byte has been read */
  395.  
  396.     if (flag_byte < 4) {    /* short preamble */
  397.         packet_length = (flag_byte << 8) + get_pk_byte();
  398.         char_code = get_pk_byte();
  399.         tfm_width = get_pk_byte() << 16;
  400.         tfm_width += get_pk_word();
  401.         packet_length -= 3;    /* correct for reading tfm_width */
  402.     }
  403.     else if (flag_byte < 7) {    /* extended short preamble */
  404.         packet_length = ((flag_byte - 4) << 16) + get_pk_word();
  405.         char_code = get_pk_byte();
  406.         tfm_width = get_pk_byte() << 16;
  407.         tfm_width += get_pk_word();
  408.         packet_length -= 3;
  409.     }
  410.     else {                    /* long preamble */
  411.         packet_length = get_pk_double();
  412.         char_code = get_pk_double();
  413.         tfm_width = get_pk_double();
  414.         packet_length -= 4;
  415.     }
  416. }
  417.  
  418.             /*
  419.              * This reads the char preamble starting after the tfm width,
  420.              * carrying on where get_pk_char_code() left off.
  421.              */
  422. void
  423. get_pk_char_dimen()
  424. {
  425.     if (flag_byte < 4) {    /* short preamble */
  426.         hor_esc = get_pk_byte();
  427.         char_width = get_pk_byte();
  428.         word_width = (char_width + 15)>>4;
  429.         char_height = get_pk_byte();
  430.         h_off = (char)get_pk_byte();
  431.         v_off = (char)get_pk_byte();
  432.     }
  433.     else if (flag_byte < 7) {    /* extended short preamble */
  434.         hor_esc = get_pk_word();
  435.         char_width = get_pk_word();
  436.         word_width = (char_width + 15)>>4;
  437.         char_height = get_pk_word();
  438.         h_off = (short)get_pk_word();
  439.         v_off = (short)get_pk_word();
  440.     }
  441.     else {                    /* long preamble */
  442.         hor_esc = get_pk_double();
  443.         vert_esc = get_pk_double();
  444.         char_width = get_pk_double();
  445.         word_width = (char_width + 15)>>4;
  446.         char_height = get_pk_double();
  447.         h_off = get_pk_double();
  448.         v_off = get_pk_double();
  449.     }
  450. }
  451.  
  452.  
  453.             /*
  454.              * This reads the preamble for one character.
  455.              */
  456. void
  457. get_pk_char_preamble()
  458. {
  459.     flag_byte = get_pk_byte();
  460.     get_pk_char_code();
  461.     get_pk_char_dimen();
  462. }
  463.  
  464.  
  465. /*
  466.  * Now here are the routines called by the rest of textool
  467.  */
  468.  
  469. /*-->FindFontFile*/
  470.  
  471. void
  472. FindFontFile(tfontptr, mag)
  473. struct font_entry *tfontptr;
  474. unsigned int mag;
  475. {
  476.     char *direct, *tcp, *tcp1;
  477.     int found;
  478.     char curarea[STRSIZE];
  479.  
  480.     tfontptr->font_mag = (int)(
  481.         ActualFactor((int)(((float)tfontptr->s/(float)tfontptr->d)*1000.0+0.5))
  482. #ifdef USEGLOBALMAG
  483.                         * ActualFactor(mag)
  484. #endif
  485.                         * (float)RESOLUTION + 0.5);
  486. #ifdef DEBUG
  487.     if (ExtraDebug) {
  488.         fprintf(stderr, "FindFontFile():\n");
  489.         fprintf(stderr, "  mag = %d\n", mag);
  490.         fprintf(stderr, "  s = %d\n", tfontptr->s);
  491.         fprintf(stderr, "  d = %d\n", tfontptr->d);
  492.         fprintf(stderr, "  font_mag = %d\n", tfontptr->font_mag);
  493.     }
  494. #endif
  495.     if (tfontptr->a != 0) {
  496.         sprintf(tfontptr->name, "%s.%dpk", tfontptr->n, tfontptr->font_mag);
  497.     } else {
  498.         direct = PKpath;
  499.         found = FALSE;
  500.         do { 
  501.             tcp = index(direct, ':');
  502.             if (tcp == NULL) tcp = strlen(direct) + direct;
  503.             strncpy(curarea, direct, tcp-direct);
  504.             tcp1 = curarea + (tcp - direct);
  505.             *tcp1++ = '/';
  506.             *tcp1++ = '\0';
  507.  
  508.             sprintf(tfontptr->name, "%s%s.%dpk",
  509.                     curarea, tfontptr->n, tfontptr->font_mag);
  510.             found = (access(tfontptr->name, R_OK) == 0);
  511.             if (*tcp) direct = tcp + 1; else direct = tcp;
  512.         } while ( !found && *direct != '\0');
  513.     }
  514. #ifdef DEBUG
  515.     if (ExtraDebug)
  516.         fprintf(stderr, "FindFontFile() returns with name %s\n",
  517.                 tfontptr->name);
  518. #endif
  519. }
  520.  
  521.  
  522. /*-->LoadAChar*/
  523.  
  524. void
  525. LoadAChar(ptr)
  526. register struct char_entry *ptr;
  527. {
  528.     register Pixrect *pr;
  529.     register short *dp;
  530.  
  531.     pkfp = OpenFontFile();
  532.     if (ptr->where.address.fileOffset == 0) {
  533.         ptr->where.address.pixrectptr = NULL;
  534.         return;
  535.     }
  536.     fseek(pkfp, ptr->where.address.fileOffset, 0);
  537.     get_pk_char_preamble();
  538.     ptr->width = char_width;
  539.     ptr->height = char_height;
  540.     ptr->xOffset= h_off;
  541.     ptr->yOffset = v_off;
  542.     if ((pr = mem_create(ptr->width, ptr->height, 1)) == NULL) {
  543.         Fatal("Couldn't allocate pixrect");
  544.         return;
  545.     }
  546.     dp = ((struct mpr_data *)pr->pr_data)->md_image;
  547.     if (dyn_f == 14)
  548.         bitmap_raster(dp);
  549.     else
  550.         normal_raster(dp);
  551.     ptr->where.address.pixrectptr = pr;
  552.     ptr->where.isloaded = TRUE;
  553. }
  554.  
  555.  
  556. /*-->ReadCharDefs*/
  557.  
  558. void
  559. ReadCharDefs(tfontptr, fp)
  560. struct font_entry *tfontptr;
  561. FILE *fp;
  562. {
  563.     register struct char_entry *tcharptr; /* temporary char_entry pointer */
  564.     register Pixrect *pr;
  565.     register int junk_count;
  566.     short *dp;
  567.  
  568. #ifdef DEBUG
  569.     if (ExtraDebug)
  570.         fprintf(stderr, "ReadCharDefs() for font %s\n", tfontptr->name);
  571. #endif
  572.     pkfp = fp;
  573.     get_pk_preamble();
  574.     skip_specials();
  575.     while (!got_pk_post) {
  576.         get_pk_char_code();
  577.         tcharptr = &(tfontptr->ch[char_code]);
  578.         tcharptr->tfmw = tfm_width * (float)tfontptr->s / (float)(1<<20);
  579.         if (BigPreLoad) {
  580.             /*
  581.              * Load the rest of the character info.
  582.              */
  583.             get_pk_char_dimen();
  584.             tcharptr->width = char_width;
  585.             tcharptr->height = char_height;
  586.             tcharptr->xOffset= h_off;
  587.             tcharptr->yOffset = v_off;
  588.             if ((pr = mem_create(char_width, char_height, 1)) == NULL) {
  589.                 Fatal("Couldn't allocate pixrect");
  590.                 return;
  591.             }
  592.             dp = ((struct mpr_data *)pr->pr_data)->md_image;
  593.             if (dyn_f == 14)
  594.                 bitmap_raster(dp);
  595.             else
  596.                 normal_raster(dp);
  597.             tcharptr->where.address.pixrectptr = pr;
  598.             tcharptr->where.isloaded = TRUE;
  599.         }
  600.         else {
  601.             tcharptr->where.isloaded = FALSE;
  602.             tcharptr->where.address.fileOffset = pk_char_start;
  603.             /*
  604.              * Otherwise skip the rest of the char.
  605.              * The bytes are read rather than using fseek as the pk files
  606.              * are small and the whole thing is likely to fit in one stdio
  607.              * buffer so this will not involve any function calls.
  608.              */
  609.             junk_count = packet_length;
  610.             while (junk_count--)
  611.                 getc(pkfp);
  612.             pk_loc += packet_length;
  613.         }
  614.         skip_specials();
  615.     }
  616. }
  617.  
  618.  
  619.